package org.dyndns.opendemogroup.optimizer;

import static org.junit.Assert.*;

import org.dyndns.opendemogroup.optimizer.problems.OneMax;
import org.junit.Test;

/**
 * A class to test the class Member
 */
public class MemberTest
{

	/**
	 * Tests the <i>getFitness</i> method with a OneMax problem of size 10,
	 * where all alleles are ones.
	 */
	@Test
	public void getFitness_TypicalOneMax ( )
	{
		int memberSize = 10;
		OneMax problem = new OneMax ( memberSize );
		Member member = new Member ( memberSize );
		for ( int i = 0; i < memberSize; i++ )
		{
			member.genome[i] = 1;
		}
		member.decode ( problem, null );
		double actual = member.getFitness ( );
		double expected = 10.0;
		assertEquals ( expected, actual );
	}

	/**
	 * Tests the <i>compareTo</i> method with a OneMax problem of size 10, and
	 * alleles are alternating between ones and zeroes, but the fitnesses are
	 * identical.
	 */
	@Test
	public void compareTo_TypicalOneMax ( )
	{
		int memberSize = 10;
		OneMax problem = new OneMax ( memberSize );
		Member member = new Member ( memberSize );
		Member o = new Member ( memberSize );
		for ( int i = 0; i < memberSize; i++ )
		{
			member.genome[i] = i % 2;
			o.genome[i] = ( i + 1 ) % 2;
		}
		member.decode ( problem, null );
		o.decode ( problem, null );
		int actual = member.compareTo ( o );
		int expected = 0;
		assertEquals ( expected, actual );
	}

	/**
	 * Tests the <i>copyFrom</i> method with a OneMax problem of size 10,
	 * initializing the genomes with alternating patterns, copying all of source
	 * onto member and then comparing them.
	 */
	@Test
	public void copyFrom_TypicalOneMax ( )
	{
		int memberSize = 10;
		OneMax problem = new OneMax ( memberSize );
		Member member = new Member ( memberSize );
		Member source = new Member ( memberSize );
		for ( int i = 0; i < memberSize; i++ )
		{
			member.genome[i] = i % 2;
			source.genome[i] = ( i + 1 ) % 2;
		}
		int startIndex = 0;
		int endIndex = memberSize - 1;
		member.copyFrom ( source, startIndex, endIndex );

		source.decode ( problem, null );
		member.decode ( problem, null );
		double expectedFitness = source.getFitness ( );
		double actualFitness = member.getFitness ( );
		assertEquals ( expectedFitness, actualFitness );

		for ( int i = 0; i < memberSize; i++ )
		{
			assertEquals ( source.genome[i], member.genome[i] );
		}
	}

	/**
	 * Tests the <i>toString</i> method with a typical scenario of a genome
	 * initialized with a 10-allele pattern from OneMax.
	 */
	@Test
	public void toString_Typical ( )
	{
		int memberSize = 10;
		Member member = new Member ( memberSize );
		for ( int i = 0; i < memberSize; i++ )
		{
			member.genome[i] = i % 2;
		}
		String actual = member.toString ( );
		String expected = "[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]";
		assertEquals ( expected, actual );
	}

	/**
	 * Tests the <i>clone</i> method with a typical scenario.
	 * 
	 * @throws CloneNotSupportedException
	 *         This should never happen and would constitute a failure of the
	 *         unit test!
	 */
	@Test
	public void clone_Typical ( ) throws CloneNotSupportedException
	{
		int memberSize = 50;
		Member original = new Member ( memberSize );
		for ( int i = 0; i < memberSize; i++ )
		{
			original.genome[i] = 1.0;
		}

		Member copy = (Member) original.clone ( );
		for ( int i = 0; i < memberSize; i++ )
		{
			assertEquals ( 1.0, copy.genome[i] );
		}

		for ( int i = 0; i < memberSize; i++ )
		{
			original.genome[i] = 0.0;
		}

		for ( int i = 0; i < memberSize; i++ )
		{
			assertEquals ( 1.0, copy.genome[i] );
		}
	}

}
